﻿@using ApiLib.RCL.Utils
@using ApiLib.RCL.Components
@using ApiLib.RCL.Components.AutoTable.Attributes
@using ApiLib.RCL.Components.AutoTable.Models
@using ApiLib.RCL.Components.AutoTable.Utils
@using Console = System.Console

@typeparam TItem where TItem : IAutoTable<TItem>

@inject MessageService message
@inject SwalService swal

@switch (_fieldType)
{
    case TableFieldType.Input:
        <BootstrapInput @bind-Value="@str_value" IsDisabled="_disable"
                        OnValueChanged="OnStrValueChanged" TValue="string"
                        type="@_showType" PlaceHolder="@_placeHolder"/>
        break;
    case TableFieldType.InputNumber:
        <BootstrapInputNumber @bind-Value="@int_value" IsDisabled="_disable"
                              OnValueChanged="OnIntValueChanged"
                              TValue="int"
                              Step="int" PlaceHolder="@_placeHolder"/>
        break;
    case TableFieldType.InputDouble:
        <BootstrapInputNumber @bind-Value="double_value" IsDisabled="_disable"
                              TValue="double" OnValueChanged="OnDoubleValueChanged"
                              Step="double" PlaceHolder="@_placeHolder"/>
        break;
    case TableFieldType.TextArea:
        <Textarea @bind-Value="str_value" TValue="string" OnValueChanged="OnStrValueChanged" IsDisabled="_disable"
                  placeholder="@_placeHolder" rows="3"></Textarea>
        break;
    case TableFieldType.Markdown:
        <CherryMarkdown IsViewer="@_disable" OnFileUpload="OnFileUpload" Value="@str_value"
                        ValueChanged="OnStrValueChanged2"/>
        break;
    case TableFieldType.Radio:
        <RadioList @bind-Value="str_value" Items="_items"
                   IsDisabled="_disable" ShowBorder="false"
                   OnValueChanged="OnStrValueChanged"
                   TValue="string">
        </RadioList>
        break;
    case TableFieldType.CheckBox:
        <CheckboxList @bind-Value="str_value" Items="_items"
                      IsDisabled="_disable" OnValueChanged="OnStrValueChanged" TValue="string"/>
        break;
    case TableFieldType.Select:
        if (_disable)
        {
            @if (_showType == "int")
            {
                <BootstrapInput @bind-Value="@int_value" IsDisabled="_disable"
                                OnValueChanged="OnIntValueChanged" TValue="int"
                                type="text" PlaceHolder="@_placeHolder"/>
            }
            else
            {
                <BootstrapInput @bind-Value="@str_value" IsDisabled="_disable"
                                OnValueChanged="OnStrValueChanged" TValue="string"
                                type="text" PlaceHolder="@_placeHolder"/>
            }
        }
        else
        {
            @if (_showType == "int")
            {
                <Select @bind-Value="int_value" Items="_items" OnValueChanged="OnIntValueChanged"
                        IsDisabled="_disable" PlaceHolder="@_placeHolder" TValue="int">
                </Select>
            }
            else
            {
                <Select @bind-Value="str_value" Items="_items" OnValueChanged="OnStrValueChanged"
                        IsDisabled="_disable" PlaceHolder="@_placeHolder" TValue="string">
                </Select>
            }
        }

        break;
    case TableFieldType.MultiSelect:
        <MultiSelect @bind-Value="str_value" Items="_items" OnValueChanged="OnStrValueChanged"
                     IsDisabled="_disable" PlaceHolder="@_placeHolder" TValue="string">
        </MultiSelect>
        break;
    case TableFieldType.Date:
        <DateTimePicker @bind-Value="datetime_value" IsDisabled="_disable"
                        OnValueChanged="OnDateValueChanged"
                        ViewMode="_dateViewMode"
                        DateFormat="@_dateViewFormat"/>
        break;
    case TableFieldType.DateRange:
        <DateTimeRange @bind-Value="datetime_range_value" IsDisabled="_disable"
                       OnValueChanged="OnDateRangeValueChanged"
                       OnClearValue="OnClearValue"
                       ViewMode="_dateViewMode"
                       DateFormat="@_dateViewFormat"/>
        break;
    case TableFieldType.DateYear:
        <DateTimePicker @bind-Value="datetime_value" IsDisabled="_disable"
                        OnValueChanged="OnDateYearValueChanged"
                        ViewMode="DatePickerViewMode.Year"
                        DateFormat="yyyy"/>
        break;
    case TableFieldType.DateMonth:
        <DateTimePicker @bind-Value="datetime_value" IsDisabled="_disable"
                        OnValueChanged="OnDateMonthValueChanged"
                        ViewMode="DatePickerViewMode.Month"
                        DateFormat="yyyy-MM"/>
        break;
    case TableFieldType.File or TableFieldType.Image:
        if (_disable)
        {
            <FileViewComponent FilePaths="@str_value"></FileViewComponent>
        }
        else
        {
            <CardUpload TValue="string" IsSingle="@_isSingle"
                        IsMultiple="@_isMultiple"
                        Accept="image_album/*"
                        IsDisabled="_disable" DefaultFileList="_uploadFiles"
                        ShowProgress="true" OnChange="@OnFileChange" OnDelete="OnFileDelete">
            </CardUpload>
        }

        break;
}

@code {

    /// <summary>
    /// 列属性
    /// </summary>
    [Parameter]
    public ColumnAttribute ColumnAttribute { get; set; } // = new();

    /// <summary>
    /// 是否禁止编辑
    /// </summary>
    [Parameter]
    public bool IsDisabled { get; set; }

    [Parameter] public TItem Entity { get; set; }
    /// <summary>
    /// 
    /// </summary>
    private TableAttribute _tableAttribute = new();

    /// <summary>
    /// 是否是查询条件
    /// </summary>
    [Parameter]
    public bool IsSearch { get; set; }
    /*[Parameter]
    public Dictionary<string, object> Data { get; set; }

    [Parameter]
    public EventCallback<Dictionary<string, object>> DataChanged { get; set; }*/

    private TableFieldType _fieldType;
    private bool _disable;
    private string _showType = "";
    private bool _isSingle = false;
    private bool _isMultiple = false;
    private string _placeHolder = "";
    private IEnumerable<SelectedItem>? _items;

    private DatePickerViewMode _dateViewMode = DatePickerViewMode.DateTime;
    private string _dateViewFormat = "yyyy-MM-dd HH:mm:ss";

    // private List<UploadFile> imgUrl = new();
    // private List<string> PreviewList { get; } = new();
    private List<UploadFile> _uploadFiles = new();
    private Dictionary<UploadFile, string> _uploadFileDict = new();
    private static long MaxFileLength => 5 * 1024 * 1024;

    private string str_value = "";
    private int int_value;
    private double double_value;
    private DateTime? datetime_value; // = DateTime.Now;
    private DateTimeRangeValue? datetime_range_value; // = new() { Start = DateTime.Now.AddMonths(-1), End = DateTime.Now };
    private string _showName = "";

    private string _host => Entity.GetHost();

    protected override async Task OnInitializedAsync()
    {
        var fieldInfo = ColumnAttribute;
        _fieldType = fieldInfo.FieldType;
        _showType = fieldInfo.ShowType;
        _disable = IsDisabled;
        _placeHolder = !string.IsNullOrEmpty(fieldInfo.Placeholder) ? fieldInfo.Placeholder : $"请输入{fieldInfo.Name}";

        if (_fieldType is TableFieldType.Date or TableFieldType.DateRange)
        {
            //作为查询条件时显示为时间范围框
            if (IsSearch && _fieldType is TableFieldType.Date)
            {
                _fieldType = TableFieldType.DateRange;
            }

            _dateViewFormat = fieldInfo.GetDateFormat();
            _dateViewMode = fieldInfo.GetDateMode();
            if (_fieldType is TableFieldType.DateRange && _dateViewMode is DatePickerViewMode.DateTime)
            {
                _dateViewMode = DatePickerViewMode.Date;
                _dateViewFormat = "yyyy-MM-dd";
            }
        }

        if (fieldInfo.FieldType is TableFieldType.Select or TableFieldType.MultiSelect
            or TableFieldType.Radio or TableFieldType.CheckBox)
        {
            _items = fieldInfo.GetSelectedItems() ?? await Entity.GetSelectedItems(fieldInfo.Name);
        }

        if (fieldInfo.FieldType is TableFieldType.Input && string.IsNullOrEmpty(_showType))
        {
            _showType="text";
        }

        var obj = fieldInfo.Value;

        switch (_fieldType)
        {
            case TableFieldType.InputNumber:
                int_value = obj is int intValue ? intValue : 0;
                break;
            case TableFieldType.InputDouble:
                double_value = obj is double doubleValue ? doubleValue : 0;
                break;
            case TableFieldType.DateYear:
                int_value = obj is int intYearValue ? intYearValue : 0;
                if (int_value > 0)
                {
                    datetime_value = new DateTime(int_value, 1, 1);
                }

                break;
            case TableFieldType.DateMonth:
                str_value = obj as string ?? "";
                if (DateTime.TryParse(str_value, out var dateTimeValue))
                {
                    datetime_value = dateTimeValue;
                }

                break;
            case TableFieldType.Date:
                datetime_value = obj as DateTime?; // dateTimeValue?dateTimeValue:DateTime.Now;
                break;
            case TableFieldType.DateRange:
                datetime_range_value = obj as DateTimeRangeValue;
                // datetime_range_value = obj as DateTimeRangeValue ?? new() { Start = DateTime.Now.AddMonths(-1), End = DateTime.Now };
                break;
            default:
                if (obj is string str)
                {
                    str_value = str;
                }

                if (_fieldType is TableFieldType.Image or TableFieldType.File)
                {
                    _isSingle = _showType?.Contains("single") ?? false;
                    _isMultiple = _showType?.Contains("multiple") ?? false;
                    var images = str_value.Split(",").Where(s => !string.IsNullOrEmpty(s));
                    foreach (var image in images)
                    {
                        // imgUrl.Add(new UploadFile() { PrevUrl = _host + image });
                        // PreviewList.Add(_host + image);
                        var uploadFile = new UploadFile() { PrevUrl = Path.Combine(_host, image), FileName = Path.GetFileName(image) };
                        /*var extension = Path.GetExtension(image);
                        if (extension is ".png" or ".jpg" or ".jpeg")
                        {
                            var format = extension switch
                            {
                                ".png" => "image/png",
                                ".jpg" => "image/jpeg",
                                ".jpeg" => "image/jpeg",
                                _ => ""
                            };
                            try
                            {
                                Console.WriteLine(_host + image);
                                var stream = await HttpUtil.DownloadAsync(_host + image);
                                if (stream != null)
                                {
                                    using var memoryStream = new MemoryStream();

                                    await stream.CopyToAsync(memoryStream);
                                    uploadFile.PrevUrl = "data:" + format + ";base64," + Convert.ToBase64String(memoryStream.ToArray());
                                    uploadFile.Code = 0;
                                }
                            }
                            catch (Exception e)
                            {
                                Console.WriteLine(e.Message);
                            }
                        }*/
                        _uploadFiles.Add(uploadFile);
                        _uploadFileDict[uploadFile] = image;
                    }
                }

                break;
        }
    }

    private async Task OnFileChange(UploadFile file)
    {
        if (file.File != null && file.File.Size > 5120000)
        {
            await NotifyWarning("图片过大");
            return;
        }

        if (file.File != null)
        {
            var res = await Entity.OnUpload(file.File);
            if (res is { code: 0 } && !string.IsNullOrEmpty(res.data))
            {
                file.PrevUrl = Path.Combine(_host, res.data);
                // await file.RequestBase64ImageFileAsync(file.File.ContentType, 640, 480, MaxFileLength);
                // PreviewList.Add(_host + res.data);

                // _uploadFiles.Add(file);
                _uploadFileDict[file] = res.data ?? "";
                await OnStrValueChanged(str_value);
            }
            else
            {
                await NotifyWarning(res?.msg ?? "请求异常");
            }
        }
    }

    private async Task<bool> OnFileDelete(UploadFile file)
    {
        // imgUrl.Remove(file);
        // PreviewList.Remove(file.PrevUrl);
        _uploadFiles.Remove(file);
        _uploadFileDict.Remove(file);
        await OnStrValueChanged(str_value);
        return true;
    }

    private Task OnIntValueChanged(int val)
    {
        ColumnAttribute.Value = int_value;
        // Data[ColumnAttribute.Name] = int_value;
        return Task.CompletedTask;
    }

    private Task OnDoubleValueChanged(double val)
    {
        ColumnAttribute.Value = double_value;
        // Data[ColumnAttribute.Name] = double_value;
        return Task.CompletedTask;
    }

    private Task OnDateValueChanged(DateTime? val)
    {
        ColumnAttribute.Value = datetime_value;
        // Data[ColumnAttribute.Name] = datetime_value;
        return Task.CompletedTask;
    }

    private Task OnDateYearValueChanged(DateTime? val)
    {
        ColumnAttribute.Value = val?.Year ?? 0;
        // Data[ColumnAttribute.Name] = datetime_value;
        return Task.CompletedTask;
    }

    private Task OnDateMonthValueChanged(DateTime? val)
    {
        ColumnAttribute.Value = val?.ToString("yyyy-MM") ?? "";
        // Data[ColumnAttribute.Name] = datetime_value;
        return Task.CompletedTask;
    }

    private Task OnDateRangeValueChanged(DateTimeRangeValue val)
    {
        ColumnAttribute.Value = datetime_range_value;
        // Data[ColumnAttribute.Name] = datetime_value;
        return Task.CompletedTask;
    }

    private Task OnStrValueChanged(string val)
    {
        if (_fieldType is TableFieldType.Image or TableFieldType.File)
        {
            var list = _uploadFileDict.Values.ToHashSet();
            // var list = PreviewList.Select(img => img.Replace(_host,"")).ToHashSet();
            str_value = string.Join(",", list);
        }

        ColumnAttribute.Value = str_value;
        // Data[ColumnAttribute.Name] = str_value;
        return Task.CompletedTask;
    }

    private async Task<string> OnFileUpload(CherryMarkdownUploadFile arg)
    {
        var stream = arg.UploadStream;
        if (stream != null && arg.FileName != null)
        {
            var res = await Entity.OnUpload(stream, arg.FileName);
            if (res is { code: 0 } && !string.IsNullOrEmpty(res.data))
            {
                return Path.Combine(_host, res.data);
            }
            else
            {
                await NotifyWarning(res?.msg ?? "请求异常");
            }
        }

        return "";
    }

    private Task OnStrValueChanged2(string? arg)
    {
        str_value = arg ?? "";
        ColumnAttribute.Value = str_value;
        // Data[ColumnAttribute.Name] = str_value;
        return Task.CompletedTask;
    }

    private Task OnClearValue(DateTimeRangeValue arg)
    {
        Console.WriteLine("这是清空按钮...");
        arg.Start = DateTime.MinValue;
        arg.End = DateTime.MinValue;
        ColumnAttribute.Value = arg;
        return Task.CompletedTask;
    }

    /// <summary>
    /// 警告
    /// </summary>
    /// <param name="content"></param>
    public async Task NotifyWarning(string content)
    {
       var isSwalNotify= Entity.GetTableAttribute()?.IsSwalNotify ?? false;
        if (isSwalNotify)
        {
            await swal.SweetWarning("提示", content);
        }
        else
        {
            await message.MessageWarning(content);
        }
    }
}